<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <!-- 
    snabbdom:
      是一个简洁，高性能的vdom lib。vue2.x的vdom和diff就是完全参考它的。
      也就说，我们就学习snabbdom的vdom和diff是一样的。snabbdom中的代码比较简单。
      面试时，面试是的原理。只需要把原理说清楚就OK了。 了解了snabbdom的diff算法，就相当于了解了vue3.x中的diff算法了。
   -->
</head>

<body>
  <div id="container"></div>
  <button id="btn-change">change</button>


  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>
  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
  <script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>

  <script>
    const snabbdom = window.snabbdom;

    // 调用init方法，得到pathch函数
    // 功能：patch函数将newVnode更新到oldVnode或elem上。
    // 初次渲染，patch函数将newVnode挂载到elem上。初次渲染是没有所谓的oldVnode
    // 首次渲染调用patch，都是更新到dom容器节点。
    // 数据变化，产生新的Vnode，新旧vnode需要对比，只去更新差异
    // patch的过程，就是diff过程，初始次渲染不需要diff。
    let patch = snabbdom.init([
      snabbdom_class,
      snabbdom_props,
      snabbdom_style,
      snabbdom_eventlisteners
    ])

    // 定义h函数
    // 功能：是一个工厂函数，根据传入的参数，生成vnode结构
    const h = snabbdom.h;


    // 调用h函数，产生vnode
    const vnode = h("ul#list", {}, [
      h('li.item', {}, "Item 1"),
      h('li.item', {}, "Item 2")
    ]);

    const container = document.getElementById("container");

    // 初次渲染，就是把vnode，转化成真实dom,挂载到容器节点上。
    // 这个过程是没有所谓的diff
    patch(container, vnode);

    document.getElementById("btn-change").addEventListener("click", () => {
      // 生在newVnode
      const newVnode = h('ul#list', {}, [
        h('li.item', {}, "Item 1"),
        h('li.item', {}, "Item B"),
        h('li.item', {}, "Item 3")
      ]);
      // 此时新旧vnode开始对比，找到差异，更新差异
      patch(vnode, newVnode)
    })
  </script>
</body>

</html>